package Controleur;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;

import Model.Dessin;
import Model.Motif;
import Model.Polygone;
import Model.Texte;
import Model.Evenement.CreationEvenement;
import Model.Evenement.Evenement;
import Model.Evenement.ModificationEvenement;
import Model.Evenement.SuppressionEvenement;
import Vue.Fenetre;

/**
 * Cette class permet de faire la liaison entre le model et la vue.
 * 
 * @author Kilian Cousein et Benjamin Tardieu
 */
public class Controleur 
{
//======================================================================//
//============================ Variables ===============================//
//======================================================================//
	
	/* Définition des différents mode */
	/**
	 * Définit le mode quand l'utilisateur est en train de créer un motif.
	 */
	public final static int MODE_CREATION = 0;
	
	/**
	 * Définit le mode quand l'utilisateur utilise la souris (ex: sélectionner, agrandir, bouger un motif). 
	 */
	public final static int MODE_SOURIS = 1;
	
	/**
	 * Définit le mode quand l'utilisateur utilise la gomme pour effacer un motif.
	 */
	public final static int MODE_GOMME = 2;
	
	/**
	 * Définit le mode quand l'utilisateur zoom dans le dessin.
	 */
	public final static int MODE_ZOOM = 3;
	
	private Dessin dessin; // dessin associé au contrôleur
	private Fenetre fenetre; // fenêtre associé au contrôleur
	private Motif motif; // dernière état du motif courant
	private int mode = MODE_SOURIS; // mode initiale de la souris
  
	
//======================================================================//
//========================== Constructeurs =============================//
//======================================================================//

	/**
	 * Crée une nouvelle instance de <i>Controleur</i> par defaut.
	 */
	public Controleur()
	{
		this.dessin = new Dessin();
		this.fenetre = new Fenetre(this, "Sans titre", 800, 600);
	}
	
	
//======================================================================//
//============================= Méthodes ===============================//
//======================================================================//

	/**
	 * Cette méthode permet de repeindre le <i>Dessin</i>. 
	 */
	public void repaintDessin()
	{
		this.fenetre.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de créer un nouveau <i>Dessin</i> du contrôleur.
	 */
	public void nouveauDessin(String nom, int largeur, int hauteur)
	{
		this.dessin = new Dessin(nom, largeur, hauteur);
		this.fenetre.dispose();
		this.fenetre = new Fenetre(this, nom, largeur, hauteur);
		this.fenetre.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet d'ouvir un fichier svg et de mettre à jour le dessin.
	 */
	public void ouvrir()
	{
		this.dessin.ouvrir();
		this.fenetre.setTitle(this.dessin.getNom()+" - DVect");
		this.fenetre.changerDimensionZoneDeDessin(new Dimension(this.dessin.getLargeur(), this.dessin.getHauteur()));
		this.fenetre.pack();
		this.fenetre.desactiverEnregistrement();
		this.fenetre.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet d'enregitrer le dessin dans un fichier préalablement déterminé ou en choisissant un.
	 */
	public void enregistrer()
	{
		if(this.dessin.enregistrer(false))
			this.fenetre.desactiverEnregistrement();
		
		this.fenetre.setTitle(this.dessin.getNom()+" - DVect");
	}
	
	
	/**
	 * Cette méthode permet d'enregistrer le dessin dans un fichier que vous devez choisir.
	 */
	public void enregistrerSous()
	{
		if(this.dessin.enregistrer(true))
			this.fenetre.desactiverEnregistrement();
	}
	
	
	/**
	 * Cette méthode permet d'exporter un dessin sous un autre format.
	 * 
	 * @param extension Format dans lequel le dessin sera enregistre.
	 */
	public void exporter(String extension)
	{
		this.dessin.exporter(extension);
	}
	
	
	/**
	 * Cette méthode permet d'annuler un <i>Evenement</i> précédemment créé.
	 */
	public void annuler()
	{
		Evenement e = this.dessin.getHistorique().getEvenementPrecedent();
		e.annuler();
		
		if(this.dessin.getHistorique().isHistoriqueEmpty())
			this.fenetre.desactiverAnnuler();
		
		this.fenetre.activerRetablir();
		this.mettreAJourMenu(true);

		this.fenetre.repaintDessin();
	}

	
	/**
	 * Cette méthode permet de rétablir un <i>Evenement</i> précédemment annulé.
	 */
	public void retablir()
	{
		Evenement e = this.dessin.getHistorique().getEvenementSuivant();
		e.retablir();
		
		if(this.dessin.getHistorique().isHistoriqueRetablirEmpty())
			this.fenetre.desactiverRetablir();
		
		this.fenetre.activerAnnuler();
		
		this.fenetre.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de dézoomer le dessin.
	 */
	public void zoomOut()
	{
		this.dessin.zoomOut();
		this.fenetre.changerDimensionZoneDeDessin(new Dimension((int) (this.dessin.getLargeur() * this.dessin.getZoom()), (int) (this.dessin.getHauteur() * this.dessin.getZoom())));
		this.fenetre.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de zoomer dans le dessin.
	 */
	public void zoomIn()
	{
		this.dessin.zoomIn();
		this.fenetre.changerDimensionZoneDeDessin(new Dimension((int) (this.dessin.getLargeur() * this.dessin.getZoom()), (int) (this.dessin.getHauteur() * this.dessin.getZoom())));
		this.fenetre.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de de zoomer dans le dessin à un point précis.
	 * 
	 * @param positionSouris Point où l'on veut zoomer.
	 */
	public void zoomIn(Point positionSouris)
	{
		this.dessin.zoomIn();
		this.fenetre.zoomerDessin(positionSouris, new Dimension(this.dessin.getLargeur(), this.dessin.getHauteur()), this.dessin.getZoom());
		this.fenetre.repaintDessin();
	}
	
	
	public void quitter()
	{
		if(!dessin.estEnregistrer())
		{					
			JOptionPane pane = new JOptionPane();			
			int choix = pane.showConfirmDialog(null, "Voulez vous enregistrer le fichier avant de quitter ?", "Quitter", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);

			if(choix == JOptionPane.YES_OPTION)	
			{
				if(dessin.enregistrer(false))	
					System.exit(0);
			}
			else if(choix == JOptionPane.NO_OPTION)
			{
				System.exit(0);
			}
			else if(choix == JOptionPane.CANCEL_OPTION)
			{	
			}
		}
		else
		{
			System.exit(0);
		}
	}
	
	
	/**
	 * Cette méthode permet changer d'outils (ex: ligne, rectangle, ...).
	 * 
	 * @param outils Nouvelle outils que l'on veut choisir.
	 */
	public void nouvelleOutils(String outils)
	{
		if(outils == "souris")
		{
			if(this.dessin.getMotif() != null)
				this.dessin.getMotif().setSelectionne(false);
			
			this.dessin.setMotif(null);
			this.mode = MODE_SOURIS;
		}
		else if(outils == "Ligne")
		{
			this.dessin.creationObjet(outils);
			this.mode = MODE_CREATION;
		}
		else if(outils == "Rectangle")
		{
			if(this.dessin.creationObjet(outils))
				this.fenetre.modifierValeurMenuBordure(this.dessin.getMotif().getLargeurBordure());
			
			this.mode = MODE_CREATION;
		}
		else if(outils == "Ellipse")
		{
			if(this.dessin.creationObjet(outils))
				this.fenetre.modifierValeurMenuBordure(this.dessin.getMotif().getLargeurBordure());
			
			this.mode = MODE_CREATION;
		}
		else if(outils == "Polygone")
		{
			if(this.dessin.creationObjet(outils))
				this.fenetre.modifierValeurMenuBordure(this.dessin.getMotif().getLargeurBordure());
			
			this.mode = MODE_CREATION;
		}
		else if(outils == "gomme")
		{
			this.dessin.setMotif(null);
			this.mode = MODE_GOMME;
		}
		else if(outils == "Texte")
		{
			if(this.dessin.creationObjet(outils))
				this.fenetre.modifierValeurMenuBordure(this.dessin.getMotif().getLargeurBordure());
			
			this.mode = MODE_CREATION;
		}
		

		this.mettreAJourMenu(true);
	}
	
	
	/**
	 * Cette méthode permet de dessiner le dessin dans la fenêtre.
	 * 
	 * @param g Variable permettant de dessiner dans une fenêtre.
	 * @param toutDessiner Permet de savoir si le contrôleur doit tout dessiner ou dessiner que le motif courant.
	 */
	public void dessiner(Graphics g, boolean toutDessiner)
	{		
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		
		if(toutDessiner)
		{
			float zoom = this.dessin.getZoom();
			g2d.scale(zoom, zoom);
			
			this.dessin.toutDessiner(g2d);
		}
		else
		{
			if(this.dessin.getMotif() != null && !this.dessin.getMotif().getSelectionne())
				this.dessin.dessiner(g2d);
		}
		
	}
	
	
	/**
	 * Retourne le motif courant du dessin.
	 * 
	 * @return Le motif courant du dessin.
	 */
	public Motif motifCourant()
	{
		return this.dessin.getMotif();
	}
	
	
	/**
	 * Retourne le zoom courant du dessin.
	 * 
	 * @return Le motif courant du dessin.
	 */
	public float zoomCourant()
	{
		return this.dessin.getZoom();
	}
	
	
	/**
	 * Retourne la couleur courante du dessin.
	 * 
	 * @return La couleur courante du dessin.
	 */
	public Color couleurCourante()
	{
		return this.dessin.getCouleur();
	}
	
	
	/**
	 * Cette méthode permet de faire correspondre les valeurs des motifs dessinés par l'utilisateur lors de la création de ce dernier au valeur de ce motif. 
	 * 
	 * @param p1 Coordonnée du début du motif lors de sa création. 
	 * @param p2 Coordonnée courante (souris).
	 */
	public void faireCorrespondreMotif(Point p1, Point p2)
	{
		this.dessin.getMotif().faireCorrespondre(p1.x, p1.y, p2.x, p2.y);
	}
	
	
	/**
	 * Cette méthode permet de déplacer un motif.
	 * 
	 * @param x Valeur du déplacement du motif sur l'axe des abscisses.
     * @param y	Valeur du déplacement du motif sur l'axe des ordonnées.
	 */
	public void deplacerMotif(int x, int y)
	{
		this.dessin.getMotif().deplacer(x, y);
		
		this.dessin.setEnregistrer(false);
		this.dessin.getHistorique().supprimerHistoriqueRetablir();
		
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
	}
	
	
	/**
     * Cette méthode permet appliquer les modifications nécessaires lors du redimensionner d'un motif par l'utilisateur.
     * 
     * @param p1 Ancienne coordonnée du motif avant sa redimensionnement. 
     * @param p2 Nouvelle coordonnée du motif après sa redimensionnement.
     */
	public void redimentionnerMotif(Point p1, Point p2)
	{
		this.dessin.getMotif().redimensionner(p1.x, p2.x, p1.y, p2.y);
		
		this.dessin.setEnregistrer(false);
		this.dessin.getHistorique().supprimerHistoriqueRetablir();
		
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
	}
	
	
	/**
	 * Cette méthode permet d'afficher les coordonnées de la souris, si cette dernière se trouve dans la zone de dessin.
	 * 
	 * @param x Position x de la souris.
	 * @param y Position y de la souris.
	 */
	public void afficherPositionSouris(int x, int y)
	{
		this.fenetre.afficherPositionSouris(x, y);
	}
	
	
	/**
	 * Cette méthode permet de retourner la poignée qui est sélectionnée. 
	 * 
	 * @return La poignée qui est sélectionnée.
	 */
	public int getSelectedHandles()
	{
		return this.dessin.getMotif().getSelectedHandle();
	}
	
	
	/**
	 * Cette méthode permet d'ajouter un motif au dessin.
	 */
	public void ajouterMotif()
	{
		this.dessin.getMotif().setSelectionne(false);

		Evenement e = new CreationEvenement(this.dessin, this.dessin.getMotif());
		this.dessin.getHistorique().ajouterEvenement(e);
		e.executer();
		
		this.dessin.setEnregistrer(false);
		this.dessin.getHistorique().supprimerHistoriqueRetablir();
		
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
		
		this.motif = this.dessin.getMotif().clone();
	}
	
	
	/**
	 * Cette méthode permet de modifier un motif se trouvant dans le dessin.
	 * 
	 * @param doitEtreDifferent
	 */
	public void modifierMotif(boolean doitEtreDifferent)
	{
		if(this.dessin.getMotif() != null && this.motif != null && (!this.dessin.getMotif().equals(this.motif) || !doitEtreDifferent))
		{
			Evenement e;
			
			if(doitEtreDifferent)
				e = new ModificationEvenement(this.dessin, this.motif, this.dessin.getMotif());
			else
				e = new ModificationEvenement(this.dessin, this.dessin.getMotif(), this.dessin.getMotif());
				
			this.dessin.getHistorique().ajouterEvenement(e);
			e.executer();
		}
				
		if(this.dessin.getMotif() != null)
			this.motif = this.dessin.getMotif().clone();
	}
	
	
	/**
	 * Cette méthode permet d'effacer un motif se trouvant dans le dessin.
	 * 
	 * @param positionSouris Supprimer le motif se trouvant à cette position.
	 * @return Vrai si le motif s'est bien supprimé. 
	 */
	public boolean effacerMotif(Point positionSouris)
	{
		Motif m;
		
		if((m = this.dessin.effacerMotif(positionSouris)) != null)
		{
			Evenement e = new SuppressionEvenement(this.dessin, m);
			this.dessin.getHistorique().ajouterEvenement(e);
			e.executer();
			
			this.dessin.setEnregistrer(false);
			this.fenetre.activerAnnuler();
			this.fenetre.desactiverRetablir();
			this.fenetre.activerEnregistrement();
			this.dessin.getHistorique().supprimerHistoriqueRetablir();

			return true;
		}
		else
			return false;
	}
	
	
	/**
	 * Cette méthode permet de sélectionner un motif se trouvant dans le dessin.
	 * 
	 * @param positionSouris Sélectionner le motif se trouvant à cette position.
	 * @param g Variable permettant de dessiner dans une fenêtre.
	 */
	public void selectionnerMotif(Point positionSouris, Graphics g)
	{
		Motif motifSelectionne = this.dessin.getMotif();
		
		if(motifSelectionne != null)
		{
			motifSelectionne.setSelectionne(false);
		}
		
		
		if(dessin.find(positionSouris))
			motifSelectionne = dessin.getMotif();
		
		if(motifSelectionne != null && motifSelectionne.getSelectionne())
		{
			this.motif = motifSelectionne.clone();
			motifSelectionne.dessinerPoignees((Graphics2D) g);
			motifSelectionne.findHandles(positionSouris);
		}
		this.mettreAJourMenu(false);
	}
	
	
	/**
	 * Cette méthode permet de mettre à jour le menu en fonction de l'outils (ex: ligne, rectangle, ...) choisi.
	 * 
	 * @param effacer Permet de savoir si on doit tout effacer le menu.
	 */
	public void mettreAJourMenu(boolean effacer)
	{
		if(this.dessin.getMotif() != null && !effacer)
		{
			String typeMotif = this.dessin.getMotif().getClass().getCanonicalName();

			if(typeMotif =="Model.Texte")
			{
				this.fenetre.afficheMenuTexte(true);
				this.fenetre.afficheMenuOpacite(true);
				this.fenetre.afficheMenuLargeurBordure(false);
				this.fenetre.afficheMenuNbCotePolygone(false);
				
				Texte texte = (Texte) this.dessin.getMotif();
				this.fenetre.modifierValeurMenuTaillePolice(texte.getTaillePolice());
				this.fenetre.modifierValeurMenuPolice(texte.getPolice());
				this.fenetre.modifierValeurMenuOpacocite((int) (texte.getOpaciteCouleur() * 100f));
			}
			else if(typeMotif =="Model.Ellipse" || typeMotif =="Model.Ligne" || typeMotif =="Model.Rectangle")
			{
				this.fenetre.afficheMenuTexte(false);
				this.fenetre.afficheMenuOpacite(true);
				this.fenetre.afficheMenuLargeurBordure(true);
				this.fenetre.afficheMenuNbCotePolygone(false);
				
				this.fenetre.modifierValeurMenuOpacocite((int) (this.dessin.getMotif().getOpaciteCouleur() * 100f));
				this.fenetre.modifierValeurMenuBordure(this.dessin.getMotif().getLargeurBordure());
			}
			else if(typeMotif =="Model.Polygone")
			{
				this.fenetre.afficheMenuTexte(false);
				this.fenetre.afficheMenuOpacite(true);
				this.fenetre.afficheMenuLargeurBordure(true);
				this.fenetre.afficheMenuNbCotePolygone(true);
				
				Polygone polygone = (Polygone) this.dessin.getMotif();
				this.fenetre.modifierValeurMenuNbCote(polygone.getNbPoint());
				this.fenetre.modifierValeurMenuOpacocite((int) (polygone.getOpaciteCouleur() * 100f));
				this.fenetre.modifierValeurMenuBordure(polygone.getLargeurBordure());
			}
			else
			{
				this.fenetre.afficheMenuTexte(false);
				this.fenetre.afficheMenuOpacite(false);
				this.fenetre.afficheMenuLargeurBordure(false);
				this.fenetre.afficheMenuNbCotePolygone(false);
			}
			
			if(this.dessin.getMotif().getSelectionne())
			{
				this.fenetre.modifierValeurMenuCouleurRemplissage(this.dessin.getMotif().getCouleur());
				this.fenetre.modifierValeurMenuCouleurBordure(this.dessin.getMotif().getCouleurBordure());
			}
			else
			{
				this.fenetre.modifierValeurMenuCouleurRemplissage(this.dessin.getCouleur());
				this.fenetre.modifierValeurMenuCouleurBordure(this.dessin.getCouleurBordure());
			}
		}
		else
		{
			this.fenetre.afficheMenuTexte(false);
			this.fenetre.afficheMenuOpacite(false);
			this.fenetre.afficheMenuLargeurBordure(false);
			this.fenetre.afficheMenuNbCotePolygone(false);
		}
	}
	
	
	/**
	 * Cette méthode permet de créer un nouvelle instance du type du motif courant du dessin.
	 */
	public void nouvelleInstanceMotif()
	{
		this.dessin.setMotif(this.dessin.getMotif().nouvelleInstance());
	}
	
	
	/**
	 * Cette méthode permet d'afficher une zone de texte pour pouvoir éditer du texte.
	 * 
	 * @param g Variable permettant de dessiner dans une fenêtre.
	 */
	public void activeZoneTexte(final Graphics g)
	{
		JTextArea jtf;
		final Motif motifSelectionne = this.dessin.getMotif();
		final Texte txt;
		
		if(motifSelectionne != null)
		{
			if(motifSelectionne.getClass().getCanonicalName() == "Model.Texte")
			{
				txt = (Texte) motifSelectionne;
				jtf = txt.getJTextArea();
				jtf.setText(txt.getTexte());
				final JFrame f = new JFrame();
				f.setLayout(new BorderLayout());
				f.setVisible(true);
				f.setMinimumSize(new Dimension(500,200));
				f.setLocation(txt.getX()+txt.getLargeur(), txt.getY());
		        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

				f.addFocusListener(new FocusListener()
				{
					public void focusLost(FocusEvent arg0) 
					{
						f.dispose();
					}
					public void focusGained(FocusEvent arg0){}
				});
				
				f.add(jtf,BorderLayout.CENTER);
				
				JPanel p = new JPanel(new BorderLayout());
				JButton bOk = new JButton("Ok");
				JButton bAnnuler = new JButton("Annuler");
				p.add(bOk,BorderLayout.EAST);
				p.add(bAnnuler, BorderLayout.WEST);
				
				bOk.addActionListener(new ActionListener()
				{
					@Override
					public void actionPerformed(ActionEvent e) 
					{
						if(txt!=null)
						{
							txt.majText((Graphics2D) g);
							if (!dessin.trouverMotif(motifSelectionne))
								ajouterMotif();
							
							fenetre.repaintDessin();
							dessin.toutDessiner((Graphics2D) g);
							f.dispose();
						}
					}
				});
				
				bAnnuler.addActionListener(new ActionListener()
				{
					@Override
					public void actionPerformed(ActionEvent e) 
					{
						f.dispose();
					}
				});
				
				f.add(p,BorderLayout.SOUTH);
			}

		}
	}
	
	
	/**
	 * Cette méthode permet de modifier la couleur du motif courant.
	 * 
	 * @param couleur Nouvelle valeur de la couleur.
	 */
	public void changerCouleurMotif(Color couleur)
	{
		this.dessin.setCouleur(couleur);
		this.fenetre.modifierValeurMenuCouleurRemplissage(couleur);
		
		if(this.dessin.getMotif() != null)
		{
			Motif motifSelectionne = this.dessin.getMotif();
			motifSelectionne.setCouleur(couleur);
			
			if(this.dessin.getMotif().getX() != -1 && this.dessin.getMotif().getY() != -1)
			{
				this.dessin.setEnregistrer(false);
				this.fenetre.activerAnnuler();
				this.fenetre.desactiverRetablir();
				this.fenetre.activerEnregistrement();
				this.dessin.getHistorique().supprimerHistoriqueRetablir();
				
				this.modifierMotif(true);
				this.repaintDessin();
			}
		}
	}
	
	
	/**
	 * Cette méthode permet de modifier la couleur de la bordure du motif courant.
	 * 
	 * @param couleur Nouvelle couleur de la bordure.
	 */
	public void changerCouleurBordure(Color couleur)
	{
		this.dessin.setCouleurBordure(couleur);
		this.fenetre.modifierValeurMenuCouleurBordure(couleur);
		
		if(this.dessin.getMotif() != null)
		{
			Motif motifSelectionne = this.dessin.getMotif();
			motifSelectionne.setCouleurBordure(couleur);
			
			if(this.dessin.getMotif().getX() != -1 && this.dessin.getMotif().getY() != -1)
			{				
				this.dessin.setEnregistrer(false);
				this.fenetre.activerAnnuler();
				this.fenetre.desactiverRetablir();
				this.fenetre.activerEnregistrement();
				this.dessin.getHistorique().supprimerHistoriqueRetablir();

				this.modifierMotif(true);
				this.repaintDessin();
			}
		}
	}
	
	
	
	/**
	 * Cette méthode permet de modifier la valeur de la largeur de la bordure du motif courant.
	 * 
	 * @param largeurBordure Nouvelle largeur de la bordure.
	 */
	public void changerLargeurBordure(int largeurBordure)
	{
		Motif motifSelectionne = this.dessin.getMotif();
		motifSelectionne.setLargeurBordure(largeurBordure);

		this.dessin.setEnregistrer(false);
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
		this.dessin.getHistorique().supprimerHistoriqueRetablir();
		
		this.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de modifier la valeur l'opacité du motif courant.
	 * 
	 * @param opacite Nouvelle valeur de l'opacité.
	 */
	public void changerOpacite(float opacite)
	{		
		Motif motifSelectionne = this.dessin.getMotif();
		motifSelectionne.setOpaciteCouleur(Float.valueOf(opacite / 100.0f));
		motifSelectionne.setOpaciteBordure(Float.valueOf(opacite / 100.0f));

		this.dessin.setEnregistrer(false);
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
		this.dessin.getHistorique().supprimerHistoriqueRetablir();
		
		this.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de modifier le nombre de coté d'un polygone.
	 *  
	 * @param nbCote Nouvelle valeur du nombre de coté d'un polygone.
	 */
	public void changerNbCotePolygone(int nbCote)
	{
		Polygone polygone = (Polygone) this.dessin.getMotif();
		polygone.setNbPoint(nbCote);
		polygone.calculerPolygone();

		this.dessin.setEnregistrer(false);
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
		this.dessin.getHistorique().supprimerHistoriqueRetablir();

		this.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de changer la taille de la police.
	 *  
	 * @param taillePolice Nouvelle valeur de la taille de la police.
	 */
	public void changerTaillePolice(int taillePolice) 
	{
		Texte txt = (Texte) this.dessin.getMotif();
		txt.setTaillePolice(taillePolice);
		
		this.dessin.setEnregistrer(false);
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
		this.dessin.getHistorique().supprimerHistoriqueRetablir();

		this.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de modifier les caractéristiques d'un texte. 
	 * 
	 * @param source 
	 */
	public void changerCaracteristiqueTexte(Object source)
	{
		Texte texte = (Texte) this.dessin.getMotif();
		JComponent bouton = (JComponent) source;

		if(bouton.getName() == "listPolice")
		{
			JComboBox j = (JComboBox) source;
			texte.setPolice(j.getSelectedItem());
		}
		else if (bouton.getName() == "gras")
			texte.modGras();
		else if(bouton.getName() == "italique")
			texte.modItalique();

		this.dessin.setEnregistrer(false);
		this.fenetre.activerAnnuler();
		this.fenetre.desactiverRetablir();
		this.fenetre.activerEnregistrement();
		this.dessin.getHistorique().supprimerHistoriqueRetablir();

		this.modifierMotif(true);
		this.repaintDessin();
	}
	
	
	/**
	 * Cette méthode permet de modifier le dernier <i>Evenement</i> de l'historique.
	 */
	public void modifierDernierEvenement()
	{
		Evenement e = this.dessin.getHistorique().popEvenementHistorique();
		e.setMotifApresEvenement(this.dessin.getMotif().clone());
		this.dessin.getHistorique().ajouterEvenement(e);
		e.executer();
		
		this.motif = this.dessin.getMotif().clone();
	}
	
	
	/**
	 * Cette méthode permet de vérifier si le motif après l'évènement du dernier évènement est égale au motif initial du dernier évènement.
	 *  
	 * @return vrai si le motif après l'évènement du dernier évènement est égale au motif initial du dernier évènement.
	 */
	public boolean motifsDernierEvenementEgaux()
	{
		return this.dessin.getHistorique().motifsDernierEvenementEgaux();
	}
	
	
	/**
	 * Cette méthode permet de supprimer le dernier évènement de l'historique.
	 */
	public void supprimerDernierEvenement()
	{
		this.dessin.getHistorique().popEvenementHistorique();
	}
	
	
	/**
	 * Cette méthode permet de retourner le vecteur de motif du dessin.
	 *  
	 * @return Le vecteur de motif.
	 */
	public Vector<Motif> getMotifs()
	{
		return this.dessin.getMotifs();
	}

//======================================================================//
//========================= Getters et Setters =========================//
//======================================================================//	
	
	/**
	 * Retourne le motif.
	 *
	 * @return motif Le motif.
	 */
	public Motif getMotif()
	{
		return motif;
	}


	/**
	 * Cette méthode permet de modifier le motif.
	 *
	 * @param motif Nouvelle valeur de <i>motif</i>.
	 */
	public void setMotif(Motif motif)
	{
		this.motif = motif;
	}
	
	
	/**
	 * Retourne le mode que l'utilisateur a choisi.
	 *
	 * @return mode Le mode.
	 */
	public int getMode()
	{
		return mode;
	}


	/**
	 * Cette méthode permet de modifier le mode.
	 *
	 * @param mode Nouvelle valeur de <i>mode</i>.
	 */
	public void setMode(int mode)
	{
		this.mode = mode;
	}

	/**
	 * Cette méthode permet de copier le motif courant.
	 *
	 */
	public void copier() 
	{
		dessin.copier();
		fenetre.getBarreOption().setEnabledColler(true);
	}
	
	/**
	 * Cette méthode permet de couper le motif courant.
	 *
	 */
	public void couper() 
	{
		dessin.couper();
		repaintDessin();
		fenetre.getBarreOption().setEnabledColler(true);
	}
	
	/**
	 * Cette méthode permet de copier le motif courant.
	 *
	 */
	public void coller() 
	{
		dessin.coller();
		repaintDessin();
	}
}